package futbol.tacticas.concursantes.FCThePatetics;

import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.SituacionJugadores;
import java.awt.Point;
import java.util.Random;
import java.util.Vector;
import static java.lang.Math.*;

public abstract class AbstractOldPathetic {

    public boolean log = false;
    public Calc calc = new Calc();
    /**Random*/
    public Random rand = new Random();

    /**Log sin salto de linea*/
    public void log(String s) {
        if (log) {
            System.out.print(s);
        }
    }

    /**Log con salto de linea*/
    public void logln(String s) {
        if (log) {
            System.out.println(s);
        }
    }

    /**Log con salto de linea*/
    public void logln() {
        logln("");
    }

    public AbstractOldPathetic() {
        for (int i = 0; i < 11; i++) {
            velocidad[i][0] = 10 - configuracion[i][2];
            velocidad[i][1] = 0;
        }
    }

    /**Retorna la fuerza de mis jugadores*/
    public int getFuerza(int jug) {
        return configuracion[jug][2];
    }

    /**Retorna la velocidad de un jugador en un equipo*/
    public int getVelocidad(int jug, int equip) {
        return velocidad[jug][equip];
    }

    /**Posicion X inicial*/
    public int getXInicial(int n) {
        return configuracion[n][0];
    }

    /**Posicion Y inicial*/
    public int getYInicial(int n) {
        return configuracion[n][1];
    }

    public int getFuerzaRival(int jug) {
        return calc.control(10 - getVelocidad(jug, 1), 4, 7);
    }

    /**Permuta al azar la posicion de los jugadores de igual fuerza*/
    public void permuta() {
        for (int i = 0; i <
                100; i++) {
            int i1 = rand.nextInt(11);
            int i2 = rand.nextInt(11);
            if (i1 != i2 && configuracion[i1][2] == configuracion[i2][2]) {
                int x0 = configuracion[i1][0];
                int y0 = configuracion[i1][1];
                configuracion[i1][0] = configuracion[i2][0];
                configuracion[i1][1] = configuracion[i2][1];
                configuracion[i2][0] = x0;
                configuracion[i2][1] = y0;
            }

        }
    }
    /**Zona de pixeles donde no se puede atrapar el valon de acuerdo con la fuerza del remate*/
    public int[] zonaMuerta = {0, 0, 0, 0, 0, 0, 56, 116};
    /**Configuracion inicial. [njug][0:x, 1:y, 2:fuerza]*/
    public final int configuracion[][] = new int[][]{{-150, 0, 4}, {-88, -88, 4}, {-88, 88, 4}, {-50, -33, 4}, {-50, 33, 4}, {0, 60, 6}, {0, -60, 6}, {92, -74, 7}, {92, 74, 7}, {45, 0, 4}, {105, 0, 7}};
    //public final int configuracion[][] = new int[][]{{-140, 15, 6}, {-140, -15, 6}, {-60, 60, 5}, {-60, -60, 5}, {0, 20, 4}, {0, -20, 4}, {50, 50, 6}, {50, -50, 6}, {100, 80, 7}, {120, 0, 7}, {100, -80, 7}};
    /**posicion actual de los jugadores*/
    public Point posJug[][] = new Point[11][2];
    /**Vector de comandos*/
    public Vector<futbol.tacticas.Comando> vector = new Vector<futbol.tacticas.Comando>();//Vector de comandos;
    /**Velocidad anterior del balon*/
    public double vel;
    /**posicion del balon, coordenada X*/
    public int balonX = 0;
    /**posicion del balon, coordenada Y*/
    public int balonY = 0;
    /**Indica cuando se a chuteado el balon*/
    public boolean chute = false;
    /**Array de potencias para alcanzar una fuerza determindad*/
    private int[][] potencia = new int[][]{
        {0, 0, 0, 0}, {19, 14, 13, 12}, {31, 25, 21, 18}, {44, 34, 29, 25},
        {100, 45, 38, 32}, {100, 100, 46, 39}, {100, 100, 100, 46}, {100, 100, 100, 100}};

    /**Determina a que distancia hay que apuntar para que el balon sea disparado con una fuerza*/
    public int getPotenciaChute(int fuerzaReal, int fuerzaRequerida) {
        fuerzaReal = calc.control(fuerzaReal, 4, 7);
        fuerzaRequerida = calc.control(fuerzaRequerida, 0, 7);
        return potencia[fuerzaRequerida][fuerzaReal - 4];
    }

    /**Chutea con un angulo y fuerza determinada*/
    public void chutear(int nJug, double ang, int fuerza) {
        int dist = getPotenciaChute(getFuerza(nJug), fuerza);
        double dx = cos(ang) * dist;
        double dy = sin(ang) * dist;
        vector.add(new ComandoGolpearBola(nJug, posJug[nJug][0].x + dx, posJug[nJug][0].y + dy));
    }

    /**Retorna el angulo y la probabilidad de anotar gol*/
    public double[] getRemate(int x, int y, int fuerza) {
        double ang1 = calc.angulo(x, y, 160, -30);
        double ang2 = calc.angulo(x, y, 160, 30);
        double ang = (ang1 + ang2) / 2;
        double dist = calc.distancia(x, y, 160, 0);
        double factor = 1;
        if (!((dist > 116 && fuerza == 7) || (dist > 56 && fuerza == 6))) {
            if (fuerza == 7) {
                factor = 116d / max(dist - 116d, 116d);
            } else if (fuerza == 6) {
                factor = 56d / max(dist - 56d, 56d);
            } else if (fuerza < 6) {
                factor = 16d / max(dist - 16d, 16d);
            }
        }
        double prov = factor * (ang2 - ang1) / (PI / 5);
        return new double[]{ang, prov};
    }

    /**Mueve un jugador hacia un posicion*/
    public void mover(int nJug, int x, int y) {
        vector.add(new ComandoIrA(nJug, x, y));
    }

    /**Chutea hacia una posicion con determinada fuerza*/
    public void chutear(int nJug, int x, int y, int fuerza) {
        double dx = x - posJug[nJug][0].x;
        double dy = y - posJug[nJug][0].y;
        if (dx != 0 && dy != 0) {
            double dist = calc.distancia(dx, dy);
            dx = dx / dist;
            dy = dy / dist;
            int f = min(getFuerza(nJug), fuerza);
            double d = 50d * (double) f / (double) getFuerza(nJug);

            double dd = d, ddx = dx, ddy = dy;
            int ff;
            do {
                dx = (int) ((double) ddx * dd);
                dy = (int) ((double) ddy * dd);
                dist = calc.distancia(dx, dy);
                ff = getFuerza(nJug) * (int) dist / 52;
                dd++;
            } while (ff < f);
            vector.add(new ComandoGolpearBola(nJug, posJug[nJug][0].x + dx, posJug[nJug][0].y + dy));
        }
    }

    /**
     * Retorna un array con la siguiente informacion:
     * [eq][jug][dato] para cada equipo y jugador donde:
     * dato=0 retorna la cantidad de iteraciones hasta recuperar el balon
     * dato=1 retorna la coordenada x donde se recuperara el balon
     * dato=2 retorna la coordenada y donde se recuperara el balon
     * @param sj
     * @return
     */
    public int[][][] estimarTrayectorias(SituacionJugadores sj) {
        chute = false;
        int[][][] ints = new int[2][11][3];
        for (int i = 0; i < 11; i++) {
            contrario[i] = posJug[i][1]; //posicion anterior del contrario

            posJug[i][0] = sj.getMisJugadores()[i]; //posicion actual de mis jugadores

            posJug[i][1] = sj.getContrario()[i]; //posicion actual del contrario

        }

        bx2 = bx1; //posicion ante-anterior del balon, eje x

        by2 = by1; //posicion ante-anterior del balon, eje y

        bx1 = balonX; //posicion anterior del balon, eje x

        by1 = balonY; //posicion anterior del balon, eje x

        Point b = sj.getBola(); //obtiene la posicion del balon

        balonX = b.x; // posicion actual del balon, eje x

        balonY = b.y; // posicion actual del balon, eje y

        if (primeraVez) {
            bx1 = balonX;
            by1 = balonY;
            bx2 = bx1;
            by2 = by1;
        }


        a0 = calc.angulo(bx1 - balonX, by1 - balonY); //direccion del balon actual

        a1 = calc.angulo(bx2 - bx1, by2 - by1); //direccion del balon anterior

        d0 = calc.distancia(bx1, by1, balonX, balonY); //velocidad del balon actual        

        vel = d0;

        d1 = calc.distancia(bx2, by2, bx1, by1); //velocidad del valon anterior

        if (d0 > 100) { // si (velocidadBalonActual>100)   ocurre despues de un gol
            //Se inicializan los parametros

            d0 = 0;//velocidadBalonActual=0

            d1 = 0;//velocidadBalonAnterior=0

            bx1 = 0;//posiconBalonAnterior=0

            by1 = 0;//posiconBalonAnterior=0

            bx2 = 0;//posiconBalonAnteAnterior=0            

            by2 = 0;//posiconBalonAnteAnterior=0

            _c0 = cc - 1;//NOSE

            _bx = 0;//NOSE

            _by = 0;//NOSE

        } else {
            if (!primeraVez) { // si no es la primera vez
                //captura la velocidad de los jugadores contrarios
                for (int i = 0; i < 11; i++) {
                    int di = (int) floor(calc.distancia(posJug[i][1].x, posJug[i][1].y, contrario[i].x, contrario[i].y));
                    if (velocidad[i][1] < di) {
                        velocidad[i][1] = di;
                    }
                }
            } else {
                bx1 = balonX;
                by1 = balonY;
                bx2 = bx1;
                by2 = by1;
                d0 = 0;
                vel = 0;
                d1 = 0;
            }
        }
        primeraVez = false;//despues de la primera vez, nunca vuelve a ser la primera

        if (d0 > 3 && (abs(a1 - a0) > .20 || abs(d1 - d0) > 5)) {// si (velBalon>3 && 
            chute = true;
            _bx = bx1;
            _by = by1;
            _c0 = cc - 1;
        }
        double n = (double) (cc - _c0);
        double d = calc.distancia(balonX, balonY, _bx, _by);
        v = max((int) round(d / n - (n + 1d) / 2d), 0);
        _bx0 = bx1;
        _by0 = by1;
        if (v > 21) {
            if (_by0 < -120) {
                _by0 = -240 - _by0;
            }

            if (_by0 > 120) {
                _by0 = 240 - _by0;
            }

            if (_bx0 < -160) {
                _bx0 = -320 - _bx0;
            }
            if (_bx0 > 160) {
                _bx0 = 320 - _bx0;
            }
        }
        bx = new int[v + 1];
        by = new int[v + 1];
        bx[v] = balonX;
        by[v] = balonY;
        if (v > 0) {
            double dist = calc.distancia(_bx, _by, balonX, balonY);
            double dx = (double) (balonX - _bx) / dist;
            double dy = (double) (balonY - _by) / dist;
            for (int i = v; i > 0; i--) {
                bx[i - 1] = bx[i] + (int) round(dx * (double) i);
                by[i - 1] = by[i] + (int) round(dy * (double) i);
                if (by[i - 1] < -120) {
                    by[i - 1] = -240 - by[i - 1];
                    dy = -dy;
                    if (i == v) {
                        _by = -240 - _by;
                        balonY = -240 - balonY;
                        by1 = -240 - by1;
                        by2 = -240 - by2;
                    }
                }
                if (by[i - 1] > 120) {
                    by[i - 1] = 240 - by[i - 1];
                    dy = -dy;
                    if (i == v) {
                        _by = 240 - _by;
                        balonY = 240 - balonY;
                        by1 = 240 - by1;
                        by2 = 240 - by2;
                    }
                }
                if (bx[i - 1] < -160) {
                    bx[i - 1] = -320 - bx[i - 1];
                    dx = -dx;
                    if (i == v) {
                        _bx = -320 - _bx;
                        balonX = -320 - balonX;
                        bx1 = -320 - bx1;
                        bx2 = -320 - bx2;
                    }
                }
                if (bx[i - 1] > 160) {
                    bx[i - 1] = 320 - bx[i - 1];
                    dx = -dx;
                    if (i == v) {
                        _bx = 320 - _bx;
                        balonX = 320 - balonX;
                        bx1 = 320 - bx1;
                        bx2 = 320 - bx2;
                    }
                }
            }
        }

        for (int eq = 0; eq < 2; eq++) {
            for (int i = 0; i < 11; i++) {
                int jm = max(min(14, v - 1), 0);
                int bx_, by_;
                if (eq == 0) {
                    bx_ = sj.getMisJugadores()[i].x;//coordenadas del jugador

                    by_ = sj.getMisJugadores()[i].y;//coordenadas del jugador

                } else {
                    bx_ = sj.getContrario()[i].x;//coordenadas del jugador

                    by_ = sj.getContrario()[i].y;//coordenadas del jugador

                }
                d1 = getVelocidad(i, eq);//velocidad del jugador

                p[i][eq] = -1;
                for (int j = jm; j > 0; j--) {
                    d0 = max(0, calc.distancia(bx_, by_, bx[j], by[j]) - 10d) / d1;
                    if (d0 < (v - j)) {
                        p[i][eq] = v - j;
                        x[i][eq] = bx[j];
                        y[i][eq] = by[j];
                        break;
                    }
                }
                if (p[i][eq] == -1) {
                    d0 = max(0, calc.distancia(bx_, by_, bx[0], by[0]) - 10d) / d1;
                    if ((d0 - floor(d0)) > 0) {
                        d0 = floor(d0) + 1;
                    } else {
                        d0 = floor(d0);
                    }
                    p[i][eq] = (int) d0;
                    x[i][eq] = bx[0];
                    y[i][eq] = by[0];
                }
            }
        }
        cc++;
        for (int eq = 0; eq < 2; eq++) {
            for (int j = 0; j < 11; j++) {
                ints[eq][j][0] = p[j][eq];
                ints[eq][j][1] = x[j][eq];
                ints[eq][j][2] = y[j][eq];
            }
        }

        return ints;
    }//################################# variables privadas ################################
    /**doubles privados*/
    private double d1,  d0,  a0,  a1;
    /**ints privados*/
    private int bx2 = 0,  bx1 = 0,  by1 = 0,  by2 = 0,  _c0 = 0,  _bx0,  _by0,  v,  _bx,  _by,  cc;
    /**velocidades calculadas de los jugadores*/
    private int[][] velocidad = new int[11][2];
    /**posicion anterior de los contrarios*/
    private Point contrario[] = new Point[11];
    /**primera vez, iteracion cero*/
    private boolean primeraVez = true;
    /**Trayectoria esperada del balon*/
    private int bx[];
    /**trayectoria esperada del balon*/
    private int by[];
    /**posicion de encuentro entre el jugador y el balon*/
    private int x[][] = new int[11][2];
    /**posicion de encuentro entre el jugador y el balon*/
    private int y[][] = new int[11][2];
    /**cantidad de pasos necesarios para recuperar el balon*/
    private int p[][] = new int[11][2];

}


